//////////////////////////////////////////////////////////////////////////
//
// GAM203
// Input Manager
// InputMgr.h
// 
// Grant Johnson
// Qantm College
// 27/10/2010
//
//////////////////////////////////////////////////////////////////////////

#ifndef INPUTMGR_H
#define INPUTMGR_H

#define DIRECTINPUT_VERSION  0x800
#include <dinput.h>
#include "Singleton.h"
#include <d3dx9.h>

class InputMgr : public Singleton<InputMgr>
{
public:
	InputMgr();
	virtual ~InputMgr();

	static const int KEYBOARD_BUFFER_SIZE = 256;  
	static const int MOUSE_BUFFER_SIZE = 64; 

	enum MouseButtonId
	{
		MouseButton_Left = 0,
		MouseButton_Right,
		MouseButton_Middle,
		MouseButton_Back,
		MouseButton_MAX,  
	};

	//////////////////////////////////////////////////////////////////////////
	// Setup Direct Input and Initialize devices
	//
	// Paramaters:
	// a_hInst, an Instance Handle
	// a_hWnd, a Window Handle
	//
	// Returns false if any step of Initialization failed
	// Returns true if Initialized successfully
	//
	//////////////////////////////////////////////////////////////////////////
	bool Setup(HINSTANCE a_hInst, HWND a_hWnd);
	
	//////////////////////////////////////////////////////////////////////////
	// Shutdown Direct Input and clean up
	//
	// Paramaters:
	// None
	//
	// Returns void
	//
	//////////////////////////////////////////////////////////////////////////
	void Shutdown(); 

	//////////////////////////////////////////////////////////////////////////
	// Update the Input, this is called every frame to capture
	// any user input
	//
	// Paramaters:
	// None
	//
	// Returns void
	//
	//////////////////////////////////////////////////////////////////////////
	void Update(); 

	//////////////////////////////////////////////////////////////////////////
	// Attemps to acquire all the devices
	//
	// Paramaters:
	// None
	//
	// Returns void
	//
	//////////////////////////////////////////////////////////////////////////
	void AcquireAll();  

	//////////////////////////////////////////////////////////////////////////
	// Called whenever the device gains or loses focus. Acquires device when gains focus
	// and Unacquires device when loses focus.
	//
	// Paramaters:
	// a_isActive, toggles acquiring/unacuiring the device
	//
	// Returns void
	//
	//////////////////////////////////////////////////////////////////////////
	void OnActivate(bool a_isActive);

	//////////////////////////////////////////////////////////////////////////
	// Setup Direct Input and Initialize devices
	//
	// Paramaters:
	// a_keyId, an ID for any keyboard key (DIK_A, DIK_B, DIK_C) etc
	//
	// Returns false if the key passed in is not pressed
	// Returns true if the key passed in is pressed
	//
	//////////////////////////////////////////////////////////////////////////
	bool IsKeyDown(DWORD a_keyId);

	//////////////////////////////////////////////////////////////////////////
	// Determines whether a key was newly pressed in the last update
	// This function is called inside the IsKeyDown function to ensure that
	// action is only performed once, as opposed to multiple times when
	// the key is held down.
	//
	// Paramaters:
	// a_keyId, an ID for any keyboard key (DIK_A, DIK_B, DIK_C) etc
	//
	// Returns false if the key passed in was not newly pressed
	// Returns true if the key passed in was newly pressed
	//
	//////////////////////////////////////////////////////////////////////////
	bool IsKeyPressed(DWORD a_keyId);

	//////////////////////////////////////////////////////////////////////////
	// Gets Buffered Mouse Data
	//
	// Paramaters:
	// a_mouseInputId, Mouse Device Constant (DIMOFS_X, DIMOFS_Y, DIMOFS_Z, DIMOFS_BUTTON0, DIMOFS_BUTTON1)
	//
	// Returns 0 if no data is available or there are no changes
	//
	//////////////////////////////////////////////////////////////////////////
	long GetMouseData(DWORD a_mouseInputId);

	//////////////////////////////////////////////////////////////////////////
	// Gets the mouse's state data
	//
	// Paramaters:
	// a_mouseButtonId, a MouseButtonId value (DIMOFS_X, DIMOFS_Y, DIMOFS_Z, DIMOFS_BUTTON0, DIMOFS_BUTTON1)
	//
	// Returns false if the mouse button is not pressed
	// Returns true if the mouse button is pressed
	//
	//////////////////////////////////////////////////////////////////////////
	bool IsMouseButtonDown(MouseButtonId a_mouseButtonId);

	//////////////////////////////////////////////////////////////////////////
	// Determines whether a mouse button was newly pressed in the last update
	// This function is called inside the IsMouseButtonDown function to ensure that
	// action is only performed once, as opposed to multiple times when
	// the mouse button is held down.
	//
	// Paramaters:
	// a_mouseButtonId, a MouseButtonId value (DIMOFS_X, DIMOFS_Y, DIMOFS_Z, DIMOFS_BUTTON0, DIMOFS_BUTTON1)
	//
	// Returns false if the key passed in was not newly pressed
	// Returns true if the key passed in was newly pressed
	//
	//////////////////////////////////////////////////////////////////////////
	bool IsMouseButtonPressed(MouseButtonId a_mouseButtonId);

	void SetMousePos(D3DXVECTOR3 a_pos);
	const D3DXVECTOR3 GetMousePos();

private:

	//Direct Input Interface
	IDirectInput8* m_pDirectInput;
	
	//Mouse Device
	IDirectInputDevice8* m_pMouse;

	//Keyboard Device
	IDirectInputDevice8* m_pKeyboard;

	//Key state buffer (see DIK_A etc; value is 0x80 if pressed)
	unsigned char m_keyState[KEYBOARD_BUFFER_SIZE];

	//Key pressed buffer (see DIK_A etc; true if key was newly pressed last Update())
	bool m_keyPressed[KEYBOARD_BUFFER_SIZE];

	//Mouse events / changes in mouse state
	DIDEVICEOBJECTDATA m_mouseData[MOUSE_BUFFER_SIZE];  
	
	//Number of valid elements in m_mouseData
	DWORD m_mouseDataCount;  
	DIMOUSESTATE m_mouseState;
	
	//Mouse button pressed buffer (true if mouse button was newly pressed last Update())
	bool m_mouseButtonPressed[MouseButton_MAX];

	D3DXVECTOR3 m_mousePos;
};

#endif  // INPUTMGR_H

